﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Drawing;
using System.Drawing.Imaging;

namespace LowLevelGraphics.SeamCarving
{
    /// <summary>
    /// Gradient class for seem carving
    /// </summary>
    public abstract class Gradient
    {
        public abstract void Recompute(BitmapData bmd, Size size);
        public byte[,] EnergyMap { get; protected set; }

        /// <summary>
        /// Normal to string property
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return "Gradient";
        }

        /// <summary>
        /// Get gradient value
        /// </summary>
        /// <param name="bmd"></param>
        /// <param name="size"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static int GetGradientValue(BitmapData bmd, Size size, int x, int y)
        {
            return -1;
        }

        /// <summary>
        /// Normalization from double to byte field
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte Normalize(double min, double max, double value)
        {
            return (byte)((value - min) * byte.MaxValue / (max - min));
        }

        /// <summary>
        /// Get energy value
        /// </summary>
        /// <param name="bmd"></param>
        /// <param name="size"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static byte GetEnergyValue(BitmapData bmd, Size size, int x, int y)
        {
            if (x >= 0 && x < size.Width && y >= 0 && y < size.Height)
            {
                unsafe
                {
                    byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride) + (x * 3);
                    // RGB to luminance formula
                    return (byte)((0.2126 * row[2]) + (0.7152 * row[1]) +
                    (0.0722 * row[0]));
                }
            }
            else
            {
                // Pixel is out of bounds, so return maximum energy
                return byte.MaxValue;
            }
        }
    }
}
